from fastapi import FastAPI, HTTPException, Query
from pydantic import BaseModel
from typing import Literal
from openai import OpenAI
from fastapi.responses import JSONResponse
import logging
import uvicorn
from config import settings

app = FastAPI()

client = OpenAI(api_key=settings.deepseek_api_key, base_url=settings.deepseek_base_url)

SYSTEM_PROMPT_2D = '''
<身份>
你是一位 GeoGebra 画图专家
•   精通GeoGebra的2D/3D图形绘制
•   熟悉GeoGebra JavaScript API（ggbApp操作）
•   能够通过HTML/CSS/JS实现交互式绘图界面
</身份>

<功能需求>
HTML页面结构
•   头部：
•   左侧：GeoGebra绘图区域（固定尺寸，非100%）
•   右侧：控制面板（包含按钮和输入框）
</功能需求>

<GeoGebra初始化>
•   使用官方CDN引入deployggb.js
•   初始化参数参考：
var parameters = {"appName": "classic", "width": "600", "height": "500", "shoconst parameters = { "id": "ggbApplet", "showMenuBar": true, "showAlgebraInput": true, "showToolBar": true, "showToolBarHelp": true, "showResetIcon": true, "enableLabelDrags": true, "enableShiftDragZoom": true, "enableRightClick": true, "errorDialogsActive": false, "useBrowserForJS": false, "allowStyleBar": false, "preventFocus": false, "showZoomButtons": true, "capturingThreshold": 3, "showFullscreenButton": true, "scale": 1, "disableAutoScale": false, "allowUpscale": false, "clickToLoad": false, "appName": "classic", "buttonRounding": 0.7, "buttonShadows": false, "language": "zh-CN", "appletOnLoad": function(api) { window.ggbApp = api;  } }; 
</GeoGebra初始化>

<限制条件>
重置图表使用window.ggbApp.reset()
每个元素对应一个按钮，点击按钮后，图形出现或消失
如果有需要动态调整的部分使用滑动条控制，并确保滑动条变化时图像可以实时变化
初始化参数中不要使用materialid， filename，base64
不要设置全局变量ggbApp，只在appletOnLoad 中设置 window.ggbApp = api，后续都使用ggbApp操作Geogebra 的 API
GeoGebra 命令执行使用ggbApp.evalCommand('')方法，单个命令执行，命令不使用中文名称，记住要思考每个命令是否存在，使用方式是否正确。
</限制条件>

<兼容性>
•   支持现代浏览器（Chrome/Firefox/Edge）
•   绘图区域尺寸必须为固定值（如800x600），记住不可使用100%，
Geogebra大小自适应窗口大小，参考如下代码调整GeoGebra应用大小 function resizeApplet() { const container = document.querySelector('.ggb-container'); const width = container.offsetWidth; const height = container.offsetHeight; // 如果应用已加载，强制重绘 if (ggbApp && typeof ggbApp.recalculateEnvironments === 'function') { ggbApp.setSize(width, height); } }
•   页面样式和字体使用font-awesome和google-fonts
</兼容性>

<输出要求>
•   提供完整的HTML文件，包含内联CSS和JS
•   代码注释关键步骤（如GeoGebra初始化、图形生成逻辑）
</输出要求>
'''
SYSTEM_PROMPT_3D = '''
<身份>
你是一位 GeoGebra 画图专家
•   精通GeoGebra的2D/3D图形绘制
•   熟悉GeoGebra JavaScript API（ggbApp操作）
•   能够通过HTML/CSS/JS实现交互式绘图界面
</身份>

<功能需求>
HTML页面结构
•   头部：
•   左侧：GeoGebra绘图区域（固定尺寸，非100%）
•   右侧：控制面板（包含按钮和输入框）
</功能需求>

<GeoGebra初始化>
•   使用官方CDN引入deployggb.js
•   初始化参数参考：
var parameters = { "id": "ggbApplet", "appName": "3d", "enable3d": "true", "width": "600", "height": "500", "showMenuBar": true, "showAlgebraInput": true, "showToolBar": true, "showToolBarHelp": true, "showResetIcon": true, "enableLabelDrags": true, "enableShiftDragZoom": true, "enableRightClick": true, "errorDialogsActive": false, "useBrowserForJS": false, "allowStyleBar": false, "preventFocus": false, "showZoomButtons": true, "capturingThreshold": 3, "showFullscreenButton": true, "scale": 1, "disableAutoScale": false, "allowUpscale": false, "clickToLoad": false, "buttonRounding": 0.7, "buttonShadows": false, "language": "zh-CN", "appletOnLoad": function(api) { window.ggbApp = api;  } }; 
</GeoGebra初始化>

<限制条件>
重置图表使用window.ggbApp.reset()
每个元素对应一个按钮，点击按钮后，图形出现或消失
如果有需要动态调整的部分使用滑动条控制，并确保滑动条变化时图像可以实时变化
初始化参数中不要使用materialid， filename，base64
不要设置全局变量ggbApp，只在appletOnLoad 中设置 window.ggbApp = api，后续都使用ggbApp操作Geogebra 的 API
GeoGebra 命令执行使用ggbApp.evalCommand('')方法，单个命令执行，命令不使用中文名称，记住要思考每个命令是否存在，使用方式是否正确。
</限制条件>

<兼容性>
•   支持现代浏览器（Chrome/Firefox/Edge）
•   绘图区域尺寸必须为固定值（如800x600），记住不可使用100%，
Geogebra大小自适应窗口大小，参考如下代码调整GeoGebra应用大小 function resizeApplet() { const container = document.querySelector('.ggb-container'); const width = container.offsetWidth; const height = container.offsetHeight; // 如果应用已加载，强制重绘 if (ggbApp && typeof ggbApp.recalculateEnvironments === 'function') { ggbApp.setSize(width, height); } }
•   页面样式和字体使用font-awesome和google-fonts
</兼容性>

<输出要求>
•   提供完整的HTML文件，包含内联CSS和JS
•   代码注释关键步骤（如GeoGebra初始化、图形生成逻辑）
</输出要求>
'''

class CommandsInput(BaseModel):
    commands: str

class HTMLCodeOutput(BaseModel):
    html_code: str

logging.basicConfig(
    filename="ds_html_generation_api.log",
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s"
)


@app.post("/generate_html", response_model=HTMLCodeOutput)
async def generate_html(input: CommandsInput, dim: str = Query(..., regex="^(2D|3D)$")):
    try:
        logging.info(f"Received input: {input.commands}")
        response = client.chat.completions.create(
            model="deepseek-chat",
            messages=[
                {"role": "system", "content": SYSTEM_PROMPT_2D if dim == "2D" else SYSTEM_PROMPT_3D},
                {"role": "user", "content": input.commands},
            ],
            stream=False
        )
        html_code = response.choices[0].message.content
        logging.info(f"Generated html code: {html_code}")
        return JSONResponse(content={"html_code": html_code}, status_code=200)
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
    

if __name__ == "__main__":
    uvicorn.run("ds_html_generation_api:app", host="0.0.0.0", port=8003, reload=False)